/**
 * Name        : FileDialog.cpp
 * Version     : 1.1.0
 * Vendor      : badadev.com
 * Description : Component for browsing directories and selecting files
 * License     : This program is free software. It comes without any warranty, to
 *               the extent permitted by applicable law. You can redistribute it
 *               and/or modify it under the terms of the Do What The Fuck You Want
 *               To Public License, Version 2, as published by Sam Hocevar. See
 *               http://sam.zoy.org/wtfpl/COPYING for more details.
 */

#include "FileDialog.h"
#include "macros.h"

#define MMC L"/Storagecard/Media"
#define PHONE L"/Media"

using namespace Osp::Base;
using namespace Osp::Base::Collection;
using namespace Osp::Graphics;
using namespace Osp::Ui;
using namespace Osp::Ui::Controls;
using namespace Osp::Io;
using namespace badadev;

FileDialog::FileDialog() : baseDir_(NULL), newDialog_(null), IsLoad(false) {
}

FileDialog::~FileDialog()
{

	if ( baseDir_ ) { delete baseDir_; }
	if ( newDialog_ ) { delete newDialog_; }
	if ( dircontentList_ ) {
		dircontentList_->RemoveAllItems();
	}
	this->RemoveAllControls();

}


result
FileDialog::Initialize(const Osp::Base::String & title, InheritanceContainer &parent, const Osp::Base::String & ext)
{
	result r;
	this->Construct(FORM_STYLE_SOFTKEY_0 | FORM_STYLE_SOFTKEY_1 | FORM_STYLE_TITLE);

	AddOrientationEventListener( *this );
	SetOrientation(ORIENTATION_AUTOMATIC_FOUR_DIRECTION);

	this->SetTitleText(title);
	this->setParent(parent);

	// Define Softkeys
	this->SetSoftkeyEnabled(SOFTKEY_0, true);
	this->SetSoftkeyEnabled(SOFTKEY_1, true);
	this->SetSoftkeyText(SOFTKEY_0, S( "IDS_NEW" ));
	this->SetSoftkeyText(SOFTKEY_1, S( "IDS_CANCEL" ));
	this->SetSoftkeyActionId(SOFTKEY_0, FileDialog::ON_NEW);
	this->SetSoftkeyActionId(SOFTKEY_1, FileDialog::ON_CANCELED);
	this->AddSoftkeyActionListener(SOFTKEY_0, *this);
	this->AddSoftkeyActionListener(SOFTKEY_1, *this);

	dircontentList_ = new List();

	dircontentList_->Construct( this->GetBounds(),
			                   LIST_STYLE_NORMAL,
			                   LIST_ITEM_SINGLE_TEXT, this->GetSize().height/6 , this->GetSize().height/6, this->GetSize().width, 0);
	dircontentList_->AddItemEventListener(*this);
	this->AddControl(*dircontentList_);
	supportExt_=ext;

	GoTop();
	// give thumbs up!
	return E_SUCCESS;
}


void FileDialog::GoTop ( void ) {
	/* select Phone/MMC */
	if ( baseDir_ ) {
		delete baseDir_;
		baseDir_ = null;
	}
	dircontentList_->RemoveAllItems();
	String entry = S( "IDS_MMC" );
	dircontentList_->AddItem(&entry, NULL, NULL, NULL, 0);
	entry = S( "IDS_PHONE" );
	dircontentList_->AddItem(&entry, NULL, NULL, NULL, 1);
	this->Draw();
	this->Show();
}

result
FileDialog::ChDir(const Osp::Base::String & base_dir)
{
	result r;
	int i=0;
	String contentType = L"";
	DirEnumerator* dircontent = NULL;


	dircontentList_->RemoveAllItems();

	if(baseDir_){delete baseDir_;}
	baseDir_ = new Directory;
	AppLog("Const " );
	r = baseDir_->Construct(base_dir);
	if(IsFailed(r))
	{
		AppLog("Failed: baseDir_->Construct(%S);", base_dir.GetPointer());
		GoTop();
		return r;
	}
	basePath_ = base_dir;

	AppLog("doodle base %S", basePath_.GetPointer());
	dircontent=baseDir_->ReadN();
	if(!dircontent){return E_IO;}

	dircontent->MoveNext();  		// Skip the same directory "."
	while(dircontent->MoveNext() == E_SUCCESS)
	{
		DirEntry dirEntry = dircontent->GetCurrentDirEntry();
		if(dirEntry.IsDirectory())
		{
			contentType=S( "IDS_DIR" );
		} else {
			contentType=S( "IDS_FILE" );
			}
		String entry(contentType + dirEntry.GetName());
		dircontentList_->AddItem(&entry, NULL, NULL, NULL, i++);

	}
	this->Draw();
	this->Show();

	delete dircontent;
	return r;
}


void
FileDialog::OnActionPerformed(const Osp::Ui::Control& source, int actionId)
{
	switch(actionId)
		{
		case FileDialog::ON_CANCELED:
			this->SetShowState(false);
			this->sendContainerActionToParent( InheritanceContainer::ON_CLOSE_ACTION );
			break;
		case FileDialog::ON_NEW:
			if ( baseDir_ ) {
			newDialog_ = new FileDialogNew();
			newDialog_->Initialize( S( "IDS_NEW_FILE" ), *this, basePath_, supportExt_, this->GetSize() );
			newDialog_->Show();
			} // else user must choose phone/mmc
			break;
		}
}

void
FileDialog::OnItemStateChanged(const Control& source, int index,
		                       int itemId, ItemStatus status)
{
	if(status==ITEM_SELECTED)
	{
		// first select
		if ( ! baseDir_ ) {
			AppLog( "first select dest" );
			switch ( itemId ) {
				case 0:
					ChDir( MMC );
				break;
				case 1:
					ChDir( PHONE );
				break;
			}
		return;
		}

		AppLog ( "item %d", itemId );
		DirEnumerator* dircontent = NULL;
		int i=-1;
		dircontent=baseDir_->ReadN();
		if(!dircontent){return;}
		dircontent->MoveNext();  		// Skip the same directory "."
		do
		{
			dircontent->MoveNext();
			i++;
		}while(i<itemId);
		DirEntry dirEntry = dircontent->GetCurrentDirEntry();
		String t_path;
		if(basePath_.EndsWith(L"/"))	{
			t_path = basePath_ + dirEntry.GetName();
		} else	{
			t_path = basePath_ + String("/") + dirEntry.GetName();
		}

		if( dirEntry.IsDirectory() ) {
			if( dirEntry.GetName()==".." ) {
				int lastindex;
				if( basePath_.LastIndexOf( "/", basePath_.GetLength()-1, lastindex ) == E_SUCCESS ) {
					basePath_.SubString(0,lastindex,t_path);
					if( lastindex == 0 ) {
						GoTop();
					}
				}
			}
			ChDir(t_path);
			RequestRedraw(true);
		} else	{
			SelectConfirm( t_path );
		}
		delete dircontent;
	}
}


void
FileDialog::SelectConfirm(Osp::Base::String filepath)
{
	MessageBox msgbox;
	String msg = S( "IDS_SELECTED_FILE" );
	bool fexit = false;

	// Open only support extensions
	// TODO: make as regexp?
	if ( File::GetFileExtension( filepath ) != supportExt_ )  {
		msg = S( "IDS_FORMAT_NOT_SUPPORTED" );
		fexit = true;
	}

	msgbox.Construct(this->GetTitleText(), msg + "" + filepath,
					 MSGBOX_STYLE_OK, 0);
	int modalresult=0;
	msgbox.ShowAndWait(modalresult);
	this->selectedFile_ = "";
	if( modalresult==MSGBOX_RESULT_OK  && !fexit )	{
		this->selectedFile_= filepath;
		AppLog (" selected %S", this->selectedFile_.GetPointer() );
		this->sendContainerActionToParent(FileDialog::ON_SELECTED);
		this->SetShowState(false);
	}
}



void FileDialog::receiveContainerActionFromChild(const int actionId, InheritanceContainer &child) {
	switch(actionId)
	{
		case FileDialogNew::ON_CREATE:{

			if(newDialog_->GetNewFilePath()!="")
			{
				this->selectedFile_ = newDialog_->GetNewFilePath();
				newDialog_->SetShowState( false );
				this->RequestRedraw(true);
				delete newDialog_;
				newDialog_ = null;
				ChDir(basePath_);
				SelectConfirm( selectedFile_ );
			}

		}
		break;
		case InheritanceContainer::ON_CLOSE_ACTION:
			if(&child==newDialog_)
			{
				newDialog_->SetShowState( false );
				delete newDialog_;
				newDialog_ = null;
				this->RequestRedraw(true);
			}
			break;

		default:
			AppLog ( "default action on FD recieve" );
		break;
	}
}


void FileDialog::OnOrientationChanged(const Osp::Ui::Control &source, Osp::Ui::OrientationStatus orientationStatus) {
	dircontentList_->SetShowState( false );
	dircontentList_->SetSize( this->GetSize() );
	dircontentList_->SetShowState( true );


	if ( newDialog_ && newDialog_->IsVisible() ) {
		delete newDialog_;
		newDialog_ = new FileDialogNew();
		newDialog_->Initialize( S( "IDS_NEW_FILE" ), *this, basePath_, supportExt_, this->GetSize() );
		newDialog_->Show();
	}


	RequestRedraw();
}
